home *** CD-ROM | disk | FTP | other *** search
/ Ham Radio 2000 / Ham Radio 2000.iso / ham2000 / misc / digivfo / a12.doc < prev    next >
Text File  |  1994-02-03  |  12KB  |  272 lines

  1. CHAPTER 12   COMPATIBILITY WITH OTHER ASSEMBLERS
  2.  
  3.  
  4. I gave heavy priority to compatibility when I designed A86; a
  5. priority just a shade behind the higher priorities of
  6. reliability, speed, convenience, and power.  For those of you who
  7. feel that "close, but incompatible" is like saying "a little bit
  8. pregnant", I'm sorry to report that A86 will not assemble all
  9. Intel/IBM/MASM programs, unmodified.  But I do think that a vast
  10. majority of programs can, with a little massaging, be made to
  11. assemble under A86.  Furthermore, the massaging can be done in
  12. such a way as to make the programs still acceptable to that old,
  13. behemoth assembler.
  14.  
  15. I have been adding compatibility features with almost every new
  16. version of A86.  Among the features added since A86 was first
  17. released are: more general forward references, double quotes for
  18. strings, "=" as a synonym for EQU, the RADIX directive, and the
  19. COMMENT directive.  If you tried feeding an old source file to a
  20. previous A86 and were dismayed by the number of error messages
  21. you got, try again: things might be more manageable now.
  22.  
  23.  
  24. Conversion of MASM programs to A86
  25.  
  26. Following is a list of the things you should watch out for when
  27. converting from MASM to A86:
  28.  
  29. 1. You need to determine whether the program was coded as a COM
  30.    program or as an EXE program.  All COM programs coded for MASM
  31.    will contain an ORG 100H directive somewhere before the start
  32.    of the code.  EXE programs will contain no such ORG, and will
  33.    often contain statements that load named segments into
  34.    registers.  If the program was coded as EXE, you must either
  35.    assemble it (using the +O option) to an OBJ file to be fed to
  36.    LINK, or you must eliminate the instructions that load segment
  37.    registers-- in a COM program they often aren't necessary
  38.    anyway, since COM programs are started with all segment
  39.    registers already pointing to the same value.
  40.  
  41.    A good general rule is: when it doubt, try assembling to an
  42.    OBJ file.
  43.  
  44. 2. You need to determine whether the program is executing with
  45.    all segment registers pointing to the same value.  Simple COM
  46.    programs that fit into 64K will typically fall into this
  47.    category.  Most EXE programs, programs that use huge amounts
  48.    of memory, and programs (such as memory-resident programs)
  49.    that take over interrupts typically have different values in
  50.    segment registers.
  51.                                                              12-2
  52.  
  53.    If there are different values in the segment registers, then
  54.    there may be instructions in the program for which the old
  55.    assembler generates segment-override prefixes "behind your
  56.    back".  You will need to find such references, and to generate
  57.    explicit overrides for them.  If there are data tables within
  58.    the program itself, a CS-override is needed.    If there are
  59.    data structures in the stack segment not accessed via a
  60.    BP-index, an SS-override is needed. If ES points to its own
  61.    segment, then an ES-override is needed for accesses (other
  62.    than STOS and MOVS destinations) to that segment.  In the
  63.    interrupt handlers to memory-resident programs, the "normal"
  64.    handler is often invoked via an indirect CALL or JMP
  65.    instruction that fetches the doubleword address of the normal
  66.    handler from memory, where it was stored by the initialization
  67.    code.  That CALL or JMP often requires a CS-override-- watch
  68.    out!
  69.  
  70.    If you want to remain compatible with the old assembler, then
  71.    code the overrides by placing the segment-register name, with
  72.    a colon, before the memory-access operand in the instruction.
  73.    If you do not need further compatibility, you can place the
  74.    segment register name before the instruction mnemonic.  For
  75.    example:
  76.  
  77.     MOV AL,CS:TABLE[SI]   ; if you want compatibility do this
  78.     CS MOV AL,TABLE[SI]   ; if not you can do it this way
  79.  
  80. 3. You should use a couple of A86's switches to maximize
  81.    compatibility with MASM.  I've already mentioned the +O switch
  82.    to produce .OBJ files.  You should also assemble with the +D
  83.    switch, which disables A86's unique parsing of constants with
  84.    leading zeroes as hexidecimal.  The RADIX command in your
  85.    program will also do this. And you should use the +G15 switch,
  86.    that disables a few other A86 features that might have reduced
  87.    compatibility. See Chapter 3 for a detailed explanation of
  88.    these switches.
  89.  
  90. 4. A86 is a bit more restrictive with respect to forward
  91.    references than MASM, but not as much as it used to be. You'll
  92.    probably need to resolve just a few ambiguous references by
  93.    appending " B" or " W" to the forward reference name.
  94.  
  95. 5. A86's macro-definition and conditional-assembly language is
  96.    different from MASM's.  Most macros can be translated by
  97.    replacing the named parameters of the old macros with the
  98.    dedicated names #n of the A86 macro language; and by replacing
  99.    ENDM with #EM.  For example, the following MASM macro:
  100.  
  101.         MOVM MACRO DEST,SRC
  102.         MOV AL,DEST
  103.         MOV SRC,AL
  104.         ENDM
  105.                                                              12-3
  106.  
  107.    would be translated by eliminating the DEST,SRC declarations
  108.    on the first line, replacing DEST with #1 and SRC with #2 in
  109.    the body of the definiation, and replacing ENDM by #EM -- the
  110.    result is the MOVM macro that I presented at the beginning of
  111.    Chapter 11.
  112.  
  113.    Other constructs have straightforward translations, as
  114.    illustrated by the following examples.  Note that examples
  115.    involving macro parameters have double hash signs, since the
  116.    condition will be tested when the macro is expanded, not when
  117.    it is defined.
  118.  
  119.    MASM construct              Equivalent A86 construct
  120.  
  121.    IFE expr                     #IF ! expr
  122.    IFB <PARM3>                  ##IF !#S3
  123.    IFNB <PARM4>                 ##IF #S4
  124.    IFIDN <PARM1>,<CX>           ##IF "#1" EQ "CX"
  125.    IFDIF <PARM2>,<SI>           ##IF "#2" NE "SI"
  126.    IFDEF symbol                 #IF DEF symbol
  127.    IFNDEF symbol                #IF ! DEF symbol
  128.    .ERR                         (any undefined symbol)
  129.    .ERRcond                     TRUE EQU 0FFFF
  130.                                 TRUE EQU cond
  131.    EXITM                        #EX
  132.    IRP ... ENDM                 #RX1L ... #ER
  133.    REPT 100 ...ENDM             #RX1(100) ... #ER
  134.    IRPC ... ENDM                #CX ... #EC
  135.  
  136.    The last three constructs, IRP, REPT, and IRPC, usually occur
  137.    within macros; but in MASM they don't have to.  The A86
  138.    equivalents are valid only within macros-- if they occur in
  139.    the MASM program outside of a macro, you duplicate them by
  140.    defining an enclosing macro on the spot, and calling that
  141.    macro once, right after it is defined.
  142.  
  143. 6. A86 supports the STRUC directive, with named structure
  144.    elements, just like MASM, with one exception: A86 does not
  145.    save initial values declared in the STRUC definition, and A86
  146.    does not allow assembly of instances of structure elements.
  147.  
  148.    For example, the MASM construct
  149.  
  150.    PAYREC STRUC
  151.       PNAME  DB 'no name given'
  152.       PKEY   DW ?
  153.    ENDS
  154.  
  155.    PAYREC 3 DUP (?)
  156.    PAYREC <'Eric',1811>
  157.  
  158.    causes A86 to accept the STRUC definition, and to define the
  159.    structure elements PNAME and PKEY correctly; but the PAYREC
  160.    initializations need to be recoded.  If it isn't vital to
  161.    initialize the memory with the specific definition values, you
  162.    could recode the first PAYREC as:
  163.                                                              12-4
  164.  
  165.    DB  ((TYPE PAYREC) * 3) DUP ?
  166.  
  167.    If you must initialize values, you do so line by line:
  168.  
  169.    DB 'Eric         '
  170.    DW ?
  171.  
  172.    If there are many such initializations, you could define a
  173.    macro INIT_PAYREC containing the DB and DW lines.
  174.  
  175. 7. A86 does not support a couple of the more exotic features of
  176.    MASM assembly language: the RECORD directive and its
  177.    associated operators WIDTH and MASK; and the usage of
  178.    angle-brackets to initialize structure records.  These
  179.    features would have added much complication to the internal
  180.    structure of symbol tables in A86, degrading the speed and the
  181.    reliability of the assembler.  I felt that their use was
  182.    sufficiently rare that it was not worth including them for
  183.    compatibility.
  184.  
  185.    If your old program does use these features, you will have to
  186.    re-work the areas that use them.  Macros can be used to
  187.    duplicate the record and structure initializations.  Explicit
  188.    symbol declarations can replace the usage of the WIDTH and
  189.    MASK operators.
  190.  
  191.  
  192. Compatibility symbols recognized by A86
  193.  
  194. A86 has been programmed to ignore a variety of lines that have
  195. meaning to Intel/IBM/MASM assemblers; but which do nothing for
  196. A86.  These include lines beginning with a percent sign, lines
  197. beginning with ASSUME, and lines beginning with any unrecognized
  198. symbol that begins with a period.  If you are porting your
  199. program to A86, and you wish to retain the option of returning to
  200. the other assembler, you may leave those lines in your program.
  201. If you decide to stay with A86, you can remove those lines at
  202. your leisure.
  203.  
  204. In addition, there is a class of symbols now recognized by A86 in
  205. its .OBJ mode, but still ignored in .COM mode.  This includes
  206. NAME, END, and PUBLIC.
  207.  
  208. Named SEGMENT and ENDS directives written for other assemblers
  209. are, of course, recognized by A86's .OBJ mode.  In non-OBJ mode,
  210. A86 treats these as CODE SEGMENT directives.  A special exception
  211. to this is the directive
  212.  
  213.     segname SEGMENT AT atvalue
  214.  
  215. which is treated by A86 as if it were the following sequence:
  216.  
  217.     segname EQU atvalue
  218.     STRUC
  219.  
  220. This will accomplish what is usually intended when SEGMENT AT is
  221. used in a program intended to be a COM file.
  222.                                                              12-5
  223.  
  224. Conversion of A86 Programs to Intel/IBM/MASM
  225.  
  226. I consider this section a bit of a blasphemy, since it's a little
  227. silly to port programs from a superior assembler, to run on an
  228. inferior one.  However, I myself have been motivated to do so
  229. upon occasion, when programming for a client not familiar with
  230. A86; or whose computer doesn't run A86, and who therefore wants
  231. the final version to assemble on Intel's assembler.  Since my
  232. assembler/debugger environment is so vastly superior to any other
  233. environment, I develop the program using my assembler, and port
  234. it to the client's environment at the end.
  235.  
  236. The main key to success in following the above scenarios is to
  237. exercise supreme will power, and not use any of the wonderful
  238. language features that exist on A86, but not on MASM. This is
  239. often not easy; and I have devised some methods for porting my
  240. features to other assemblers:
  241.  
  242. 1. I hate giving long sequences of PUSHes and POPs on separate
  243.    lines.  If the program is to be ported to a lesser assembler,
  244.    then I put the following lines into a file that only A86 will
  245.    see:
  246.  
  247.       PUSH2 EQU PUSH
  248.       PUSH3 EQU PUSH
  249.       POP2 EQU POP
  250.       POP3 EQU POP
  251.  
  252.    I define macros PUSH2, PUSH3, POP2, POP3 for the lesser
  253.    assembler, that PUSH or POP the appropriate number of
  254.    operands.  Then, everywhere in the program where I would
  255.    ordinarily use A86's multiple PUSH/POP feature, I use one or
  256.    more of the PUSHn/POPn mnemonics instead.
  257.  
  258. 2. I refrain from using the feature of A86 whereby constants with
  259.    a leading zero are default-hexadecimal.  All my hex constants
  260.    end with H.
  261.  
  262. 3. I will usually go ahead and use my local labels L0 through L9;
  263.    then at the last minute convert them to a long set of labels
  264.    in sequence: Z100, Z101, Z102, etc.  I take care to remove all
  265.    the ">" forward reference specifiers when I make the
  266.    conversion.  The "Z" is used to isolate the local labels at
  267.    the end of the lesser assembler's symbol table listing. This
  268.    improves the quality of the final program so much that it is
  269.    worth the extra effort needed to convert L0--L9's to Z100--
  270.    Zxxx's.
  271.  
  272.